home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / GRAHAM / XA_6S.ZIP / SOURCE / J_RECT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-23  |  5.8 KB  |  296 lines

  1. /*
  2.  * XaAES - XaAES Ain't the AES
  3.  *
  4.  * A multitasking AES replacement for MiNT
  5.  *
  6.  */
  7.  
  8. #include <VDI.H>
  9. #include <MINTBIND.H>
  10. #include <memory.h>
  11. #include "XA_DEFS.H"
  12. #include "XA_TYPES.H"
  13. #include "XA_GLOBL.H"
  14. #include "K_DEFS.H"
  15. #include "C_WINDOW.H"
  16. #include "EVENTS.H"
  17. #include "rectlist.h"
  18.  
  19. #define max(x,y)    (((x)>(y))?(x):(y))
  20. #define min(x,y)    (((x)<(y))?(x):(y))
  21.  
  22.  
  23. #define BLKALLOC    10        /* Elements to allocate at a time */
  24. static XA_RECT_LIST *unused = NULL;    /* List of free elements */
  25. #define ALLOC(elem)    {                    \
  26.                 if (!unused)            \
  27.                     new_elements();        \
  28.                 elem = unused;            \
  29.                 unused = unused->next;    \
  30.             }
  31. #define FREE(elem)    {                    \
  32.                   elem->next = unused;    \
  33.                 unused = elem;            \
  34.             }
  35.  
  36. /*
  37.  *    Compute intersection of two rectangles; put result rectangle
  38.  *    into *d; return TRUE if intersection is nonzero.
  39.  *
  40.  *    (Original version of this function taken from Digital Research's
  41.  *    GEM sample application `DEMO' [aka `DOODLE'],  Version 1.1,
  42.  *    March 22, 1985)
  43.  */
  44.  
  45. short rc_intersect(const GRECT *s, GRECT *d)
  46. {
  47.     short x1, y1, x2, y2;
  48.  
  49.     x1 = max(s->g_x, d->g_x);
  50.     x2 = min(s->g_x + s->g_w, d->g_x + d->g_w);
  51.     if (x2 <= x1)
  52.         return(0);
  53.  
  54.     y1 = max(s->g_y, d->g_y);
  55.     y2 = min(s->g_y + s->g_h, d->g_y + d->g_h);
  56.     if (y2 <= y1)
  57.         return(0);
  58.  
  59.     d->g_x = x1;
  60.     d->g_y = y1;
  61.     d->g_w = x2 - x1;
  62.     d->g_h = y2 - y1;
  63.     return(1);
  64. }
  65.  
  66. static int intersect(const XA_RECT_LIST *s, const XA_WINDOW *d, XA_RECT_LIST *r)
  67. {
  68.     short x1, y1, x2, y2;
  69.  
  70.     x1 = max(s->x, d->x);
  71.     x2 = min(s->x + s->w, d->x + d->w);
  72.     if (x2 <= x1)
  73.         return(0);
  74.  
  75.     y1 = max(s->y, d->y);
  76.     y2 = min(s->y + s->h, d->y + d->h);
  77.     if (y2 <= y1)
  78.         return(0);
  79.     
  80.     r->x = x1;
  81.     r->y = y1;
  82.     r->w = x2 - x1;
  83.     r->h = y2 - y1;
  84.  
  85.     return(1);
  86. }
  87.  
  88. static int w_intersect(const XA_RECT_LIST *s, const XA_WINDOW *d, XA_RECT_LIST *r)
  89. {
  90.     short x1, y1, x2, y2;
  91.  
  92.     x1 = max(s->x, d->wx);
  93.     x2 = min(s->x + s->w, d->wx + d->ww);
  94.     if (x2 <= x1)
  95.         return(0);
  96.  
  97.     y1 = max(s->y, d->wy);
  98.     y2 = min(s->y + s->h, d->wy + d->wh);
  99.     if (y2 <= y1)
  100.         return(0);
  101.     
  102.     r->x = x1;
  103.     r->y = y1;
  104.     r->w = x2 - x1;
  105.     r->h = y2 - y1;
  106.  
  107.     return(1);
  108. }
  109.  
  110. static void new_elements(void)
  111. {
  112.     int i;
  113.     
  114.     unused = (XA_RECT_LIST *)malloc(BLKALLOC * sizeof(XA_RECT_LIST));
  115.     for(i = 0; i < BLKALLOC - 1; i++)
  116.         unused[i].next = &unused[i + 1];
  117.     unused[BLKALLOC - 1].next = NULL;
  118. #ifdef RL_DIAGS
  119.     DIAGS(("New rectangles (%ld)\n", (long)unused));
  120. #endif
  121. }
  122.  
  123.  
  124. XA_RECT_LIST *create_work_list(XA_WINDOW *w)
  125. {
  126.     XA_RECT_LIST *rl, *work, *cnrl, isect;
  127.     
  128.     rl = w->rl_full;
  129.     work = NULL;
  130.  
  131. #ifdef RL_DIAGS
  132.     DIAGS(("Creating new worklist\n"));
  133. #endif
  134.  
  135.     while(rl) {
  136.         if (w_intersect(rl, w, &isect)) {
  137.             ALLOC(cnrl);
  138.             cnrl->x = isect.x;
  139.             cnrl->y = isect.y;
  140.             cnrl->w = isect.w;        /* Was + 1 */
  141.             cnrl->h = isect.h;        /* Was + 1 */
  142.             cnrl->next = work;
  143.             work = cnrl;
  144.         }
  145.         rl = rl->next;
  146.     }
  147.     
  148.     return(work);
  149. }
  150.  
  151. static void free_rl_list(XA_RECT_LIST *list)
  152. {
  153.     XA_RECT_LIST *cur;
  154.  
  155.     if (!list)
  156.         return;
  157.  
  158.     cur = list;
  159.     while(cur->next)
  160.         cur = cur->next;
  161.     cur->next = unused;
  162.     unused = list;
  163.  
  164. }
  165.  
  166. /*
  167.     Rectangle List Generator 
  168.     - generates a list of clipping rectangles for a given window.
  169. */
  170.  
  171. XA_RECT_LIST *generate_rect_list(XA_WINDOW *w)
  172. {
  173.     XA_WINDOW *wl;
  174.     XA_RECT_LIST *rl, *rlist, *nrl, *cnrl;
  175.     GRECT r_ours, r_win;
  176.     XA_RECT_LIST *rlnext, isect;
  177.  
  178. #ifdef RL_DIAGS
  179.     DIAGS(("Generating new rectlist\n"));
  180. #endif
  181.  
  182.     ALLOC(rlist);    
  183.     rlist->x = w->x;
  184.     rlist->y = w->y;
  185.     rlist->w = w->w;
  186.     rlist->h = w->h;
  187.     rlist->next = NULL;
  188.  
  189.     Psemaphore(2,WIN_LIST_SEMAPHORE,-1L);
  190.     
  191.     wl = w->prev;
  192.     while(wl)
  193.     {
  194.         if (wl->is_open)
  195.         {
  196.  
  197.             nrl = NULL;
  198.             for(rl = rlist; rl; rl = rlnext)
  199.             {
  200.                 rlnext = rl->next;
  201.  
  202.                 if (!intersect(rl, wl, &isect))     /* Any overlap? */
  203.                 {
  204.                 
  205.                     rl->next = nrl;                    /* Keep the current rectangle, */
  206.                     nrl = rl;                        /* it hasn't changed */
  207.                 
  208.                 } else {
  209.                 
  210.                     if ((rl->w != isect.w) || (rl->h != isect.h))     /* Not complete covering? */
  211.                     {
  212.                     
  213.                         if (rl->x != isect.x)                        /* Not at left border? */
  214.                         {
  215.                             ALLOC(cnrl);
  216.                             cnrl->x = rl->x;
  217.                             cnrl->y = isect.y;
  218.                             cnrl->w = isect.x - rl->x;
  219.                             cnrl->h = isect.h;
  220.                             cnrl->next = nrl;
  221.                             nrl = cnrl;
  222.                         }
  223.                         
  224.                         if (isect.x + isect.w != rl->x + rl->w)     /* Not at right border? */
  225.                         {
  226.                             ALLOC(cnrl);
  227.                             cnrl->x = isect.x + isect.w;
  228.                             cnrl->y = isect.y;
  229.                             cnrl->w = rl->x + rl->w - (isect.x + isect.w);
  230.                             cnrl->h = isect.h;
  231.                             cnrl->next = nrl;
  232.                             nrl = cnrl;
  233.                         }
  234.                         
  235.                         if (isect.y != rl->y)                         /* Not at top border? */
  236.                         {
  237.                             ALLOC(cnrl);
  238.                             cnrl->x = rl->x;
  239.                             cnrl->y = rl->y;
  240.                             cnrl->w = rl->w;
  241.                             cnrl->h = isect.y - rl->y;
  242.                             cnrl->next = nrl;
  243.                             nrl = cnrl;
  244.                         }
  245.                         
  246.                         if(isect.y + isect.h != rl->y + rl->h)         /* Not at bottom border? */
  247.                         {
  248.                             ALLOC(cnrl);
  249.                             cnrl->x = rl->x;
  250.                             cnrl->y = isect.y + isect.h;
  251.                             cnrl->w = rl->w;
  252.                             cnrl->h = rl->y + rl->h - (isect.y + isect.h);
  253.                             cnrl->next = nrl;
  254.                             nrl = cnrl;
  255.                         }
  256.                         
  257.                         FREE(rl);        /* Now split, so throw away original!
  258.  
  259.                     } else {
  260.  
  261.                         FREE(rl);        /* Invisible - throw away! */
  262.  
  263.                     }
  264.                 }
  265.             }
  266.             rlist = nrl;
  267.         }
  268.         wl = wl->prev;
  269.     }
  270.     
  271.     Psemaphore(3, WIN_LIST_SEMAPHORE, 0L);
  272.     
  273.     return(rlist);
  274. }
  275.  
  276.  
  277. void invalidate_rect_lists(XA_WINDOW *wind)
  278. {
  279. #ifdef RL_DIAGS
  280.     DIAGS(("Invalidating lists\n"));
  281. #endif
  282.     Psemaphore(2,WIN_LIST_SEMAPHORE,-1L);
  283.  
  284.     while(wind) {
  285.         free_rl_list(wind->rl_full);
  286.         wind->rl_full = NULL;
  287.         free_rl_list(wind->rl_work);
  288.         wind->rl_work = NULL;
  289.         generate_rect_list(wind);        /* ++cg[29/8/96]: regenerate the rectangle lists here to avoid redraw problems */
  290.         wind = wind->next;
  291.     }
  292.  
  293.     Psemaphore(3, WIN_LIST_SEMAPHORE, 0L);
  294.  
  295. }
  296.